#include "client.hpp"

client::client()
{
    this->n = 0;
    int i = 0;
    for(; i < NB_BUFFER; i++)
    {
        this->rgb_data[i] = new unsigned char[WIDTH * HEIGHT * 3];
    }
}

client::~client()
{
    int i = 0;
    for(; i < NB_BUFFER; i++)
    {
        if(this->rgb_data[i] != nullptr){
            delete[] this->rgb_data[i];
            this->rgb_data[i] = nullptr;
        }
        if(this->resized_rgb_data[i] != nullptr){
            delete[] this->resized_rgb_data[i];
            this->resized_rgb_data[i] = nullptr;
        }
    }
    
    close(this->sockfd);
}

void client::Init(const char *argv[])
{
    struct sockaddr_in serveraddr;
    this->sockfd = -1;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    memset(&serveraddr, 0, addrlen);

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    this->sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(this->sockfd == -1)
    {
        fprintf(stderr,"socket error");
        exit(-1);
    }

    if(connect(this->sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1)
    {
        ERROR("connect is error");
    }
}

void client::recv_rgb_data(Framebuffer *ptFramebuffer)
{
    if(this->n == 6)
    {
        this->n = 0;
    }
#if 1
    int data_size = WIDTH * HEIGHT * 3;  // 24位RGB数据
#else
    int data_size = LENGTH;  // 24位RGB数据
#endif
    int packet_size = 4096;  // 单个数据包的大小
    int received_bytes = 0;

    while (received_bytes < data_size) {
        int bytes_to_recv = data_size - received_bytes;

        if(bytes_to_recv > packet_size){
            bytes_to_recv = packet_size;
        }        

        int bytes = recv(this->sockfd, this->rgb_data[this->n] + received_bytes, bytes_to_recv, 0);
        if (bytes <= 0) {
            perror("接收数据失败");
            break;
        }
        received_bytes += bytes;
    }

#if 1
    resizeRGB(this->rgb_data[this->n], WIDTH, HEIGHT, this->resized_rgb_data[this->n], ptFramebuffer->iWidth, ptFramebuffer->iHeight);
    switch(this->n)
    {
        case 0:
            rgb_to_image("output0.png");  
            break;
        case 1:
            rgb_to_image("output1.jpg");
            break;
        case 2:
            rgb_to_image("output2.jpg");
            break;
    }
#else
    decode_image(this->rgb_data[this->n], ptFramebuffer->iWidth, ptFramebuffer->iHeight, this->resized_rgb_data[this->n]);
#endif

    this->n++;
}

void client::decode_image(unsigned char* jpg_data, int new_width, int new_height, unsigned char* resized_rgb_data){
    std::vector<unsigned char> data_vec(jpg_data, jpg_data + LENGTH); // LENGTH为JPEG数据的长度
    cv::Mat decoded_img = cv::imdecode(data_vec, cv::IMREAD_COLOR);  // 解码 MJPEG 数据
    if (decoded_img.empty()) {
        std::cerr << "MJPEG 解码失败" << std::endl;
        return;
    }

    switch(this->n)
    {
        case 0:
            imwrite("output0.jpg", decoded_img);  
            break;
        case 1:
            imwrite("output1.jpg", decoded_img); 
            break;
        case 2:
            imwrite("output2.jpg", decoded_img); 
            break;
    }

    cv::Size dst_size(new_width, new_height);

    cv::Mat dst(new_height, new_width, CV_8UC3, resized_rgb_data);

    cv::resize(decoded_img, dst, dst_size);
}

void client::rgb_to_image(const char* filename)
{
    // 将 RGB 数据转换为 cv::Mat 对象
    cv::Mat image(HEIGHT, WIDTH, CV_8UC3, this->rgb_data[this->n]);

    // 将图像保存为文件
    cv::imwrite(filename, image);
}

void client::resizeRGB(unsigned char* rgb_data, int width, int height, unsigned char* resized_rgb_data, int new_width, int new_height) {
    // 目标图像的尺寸
    cv::Size dst_size(new_width, new_height);

    // 创建OpenCV Mat对象
    cv::Mat src(height, width, CV_8UC3, rgb_data);

    // 创建目标尺寸的Mat对象
    cv::Mat dst(new_height, new_width, CV_8UC3, resized_rgb_data);

    // 调整大小
    cv::resize(src, dst, dst_size);
}

void client::new_resized_rgb_data(Framebuffer *ptFramebuffer)
{
    int i = 0;
    for(; i < NB_BUFFER; i++)
    {
        this->resized_rgb_data[i] = new unsigned char[ptFramebuffer->iWidth * ptFramebuffer->iHeight * 3];
    }
}